<?php
#    pehachatpe-client - The client for the pehachatpe chat project.
#    Copyright (C) 2015 Jannik Haberbosch
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			"..",
			"sourcecode",
			"constants",
			"constants.php"
		)
	)
);

class MainFrame extends wxFrame
{
	public $menubar;
	public $wxmenu_file;
	public $wxmenu_extras;
	public $wxmenu_help;
	public $wxstatusbar;
	public $wxpanel;
	public $wxtextctrl_messages;
	public $wxlistctrl_users;
	public $wxtextctrl_message;

	public $wxhbox;
	public $wxvbox;
	public $wxvbox_allwidgets;

	public $sock;

	public $wxtimer;

	
	function __construct()
	{
		parent::__construct(null, null, "pehachatpe-client", wxDefaultPosition,
			new wxSize( 640, 480 )
		);

		$this->wxmenubar = new wxMenuBar();
		
		$this->wxmenu_file = new wxMenu();
		$this->wxmenu_file->Append(
			PEHACHATPE_WIDGET_MENU_FILE_CONNECT,
			"Connect",
			"Click here to connect to the chat-server."
		);
		$this->wxmenu_file->Append(
			PEHACHATPE_WIDGET_MENU_FILE_DISCONNECT,
			"Disconnect",
			"Click here to disconnect from the chat-server."
		);
		$this->wxmenubar->Append(
			$this->wxmenu_file,
			"Chat"
		);
		
		$this->wxmenu_extras = new wxMenu();
		$this->wxmenu_extras->Append(
			PEHACHATPE_WIDGET_MENU_EXTRAS_NICKNAME,
			"Nickname",
			"Click here to alter your nickname."
		);
		$this->wxmenu_extras->Append(
			PEHACHATPE_WIDGET_MENU_EXTRAS_SERVER_ADDRESS,
			"Chat-server address",
			"Click here to alter the address of the chat-server."
		);
		$this->wxmenu_extras->Append(
			PEHACHATPE_WIDGET_MENU_EXTRAS_SERVER_PORT,
			"Chat-server port",
			"Click here to alter the port of the chat-server."
		);
		$this->wxmenubar->Append(
			$this->wxmenu_extras,
			"Extras"
		);
		
		$this->wxmenu_help = new wxMenu();
		$this->wxmenu_help->Append(
			PEHACHATPE_WIDGET_MENU_HELP_HELP,
			"Help",
			"Click here to get help."
		);
		$this->wxmenu_help->Append(
			PEHACHATPE_WIDGET_MENU_HELP_ABOUT,
			"About",
			"Click here to get more information about the tool."
		);
		$this->wxmenubar->Append(
			$this->wxmenu_help,
			"Help"
		);

		$this->SetMenuBar($this->wxmenubar);
		$this->wxstatusbar = $this->CreateStatusBar(2);
		$this->wxstatusbar->SetStatusText("Welcome");

		$this->wxpanel = new wxPanel(
			$this
		);

		// A text widget in which all messages posted will appear.
		$this->wxtextctrl_messages = new wxTextCtrl(
			$this->wxpanel,
			PEHACHATPE_WIDGET_MESSAGES,
			wxEmptyString,
			wxDefaultPosition,
			wxDefaultSize,
			wxTE_MULTILINE
		);

		// All users that are connected to the chat are displayed here.
		$this->wxlistctrl_users = new wxListCtrl(
			$this->wxpanel,
			PEHACHATPE_WIDGET_USERS
		);

		// The client can enter a message here.
		$this->wxtextctrl_message = new wxTextCtrl(
			$this->wxpanel,
			PEHACHATPE_WIDGET_MESSAGE,
			wxEmptyString,
			wxDefaultPosition,
			wxDefaultSize,
			wxTE_PROCESS_ENTER
		);

		// Setting up our boxes to position the widgets.
		// The widget 'wxvbox_allwidgets' contains all widgets in the end.
		$this->wxhbox = new wxBoxSizer(
			wxHORIZONTAL
		);
		$this->wxvbox = new wxBoxSizer(
			wxVERTICAL
		);
		$this->wxvbox_allwidgets = new wxBoxSizer(
			wxVERTICAL
		);

		// The messages will appear in the top-left.
		$this->wxhbox->Add(
			$this->wxtextctrl_messages,
			3,
			wxEXPAND
		);
		// The list of users will appear in the top-right.
		$this->wxhbox->Add(
			$this->wxlistctrl_users,
			1,
			wxEXPAND
		);

		// Both of these widgets...
		$this->wxvbox->Add(
			$this->wxhbox,
			1,
			wxEXPAND
		);
		// ...will appear above the message widget.
		$this->wxvbox->Add(
			$this->wxtextctrl_message,
			0,
			wxEXPAND
		);

		// All three widgets are packed nicely.
		$this->wxvbox_allwidgets->Add(
			$this->wxvbox,
			1,
			wxEXPAND
		);

        // Dstribute / layout the controls in the mainframe.
        $this->wxpanel->SetSizer( $this->wxvbox );

        // Events:
        $this->Connect(
        	PEHACHATPE_WIDGET_MENU_EXTRAS_SERVER_ADDRESS,
        	wxEVT_COMMAND_MENU_SELECTED,
        	array(
        		$this,
        		"on_click_menu_extras_server_address"
        	)
        );
        $this->Connect(
        	PEHACHATPE_WIDGET_MENU_EXTRAS_SERVER_PORT,
        	wxEVT_COMMAND_MENU_SELECTED,
        	array(
        		$this,
        		"on_click_menu_extras_server_port"
        	)
        );
        $this->Connect(
        	PEHACHATPE_WIDGET_MENU_EXTRAS_NICKNAME,
        	wxEVT_COMMAND_MENU_SELECTED,
        	array(
        		$this,
        		"on_click_menu_extras_nickname"
        	)
        );
        $this->Connect(
        	PEHACHATPE_WIDGET_MENU_FILE_CONNECT,
        	wxEVT_COMMAND_MENU_SELECTED,
        	array(
        		$this,
        		"on_click_menu_file_connect"
        	)
        );
        $this->Connect(
        	PEHACHATPE_WIDGET_MENU_FILE_DISCONNECT,
        	wxEVT_COMMAND_MENU_SELECTED,
        	array(
        		$this,
        		"on_click_menu_file_disconnect"
        	)
        );
        $this->Connect(
        	PEHACHATPE_WIDGET_MESSAGE,
        	wxEVT_TEXT_ENTER,
        	array(
        		$this,
        		"on_enter_pehachatpe_widget_message"
        	)
        );

        // Timer
        $this->Connect(
        	100,
        	wxEVT_TIMER,
        	array(
        		$this,
        		"reading"
        	)
        );
        $this->wxtimer_reading = new wxTimer(
        	$this,
        	100
        );

        $this->Connect(
        	101,
        	wxEVT_TIMER,
        	array(
        		$this,
        		"writing"
        	)
        );
        $this->wxtimer_writing = new wxTimer(
        	$this,
        	101
        );


        // Initialising some properties/variables to a default value.
        $this->message_to_send = "";
		
	}
	function on_quit()
	{
		$this->Destroy();
	}


	function on_init()
	{
		/* Actions or checks that need to happen before opening the mask.
		*/
		if( !$this->exists_config_file())
		{
			file_put_contents(
				PEHACHATPE_CONFIG_FILE,
				PEHACHATPE_CONFIG_FILE_DEFAULT_CONTENT
			);
		}
	}


	function exists_config_file()
	{
		/* Returns 'True' if the configuration file exists, otherwise 'False'.
		*/

		if( file_exists( PEHACHATPE_CONFIG_FILE ))
		{
			return True;
		}
		else
		{
			return False;
		}
	}


	function config_file_alter_keyvaluepair( $_key, $_value )
	{
		/* This function takes a key and a value and alters the configuration
		file accordingly.
		It matches the key passed to this function with the key in the config-
		uration file and alters the value of that key inside the configuration
		file.
		On success, 'True' is returned, otherwise 'False'.
		
		*/
		$options = json_decode(
			file_get_contents(
				PEHACHATPE_CONFIG_FILE
			),
			TRUE // Return as an associative array.
		);

		$options[$_key] = $_value;

		$ret = file_put_contents(
			PEHACHATPE_CONFIG_FILE,
			json_encode(
				$options
			)
		);

		if( $ret == FALSE )
		{
			return FALSE;
		}
		else
		{
			return TRUE;
		}
	}


	function config_file_value_get( $_key )
	{
		/* Returns the value of a key '$_key' that matches a key in the
		configuration file.
		If the key '$_key' does not exists, 'False' is returned.

		*/
		$options = json_decode(
			file_get_contents(
				PEHACHATPE_CONFIG_FILE
			),
			TRUE // Return as an associative array.
		);

		if( array_key_exists( $_key, $options ))
		{
			return $options[$_key];
		}
		else
		{
			return FALSE;
		}
				
	}


	function on_click_menu_extras_server_address()
	{
		/* Creates and shows a dialog where the user can change the ip address
		of the chat-server he is trying to connect to.
		
		*/

		$dialog = new wxTextEntryDialog(
			$this,
			"Type in the ip-address of the server you want to connect to.",
			"Chat server ip-address",
			$this->config_file_value_get( "ip_address" )
		);

		if( $dialog->ShowModal() == wxID_OK )
		{
			$ret = $this->config_file_alter_keyvaluepair(
				"ip_address",
				$dialog->GetValue()
			);

			if( $ret == FALSE )
			{
				$dialog_error = new wxMessageDialog(
					$this,
					"The ip-address of the chat-server could not be changed.",
					"Error",
					wxICON_ERROR
				);
				$dialog_error->ShowModal();
			}
		}
	}


	function on_click_menu_extras_server_port()
	{
		/* Creates and shows a dialog where the user can change the port of
		the chat-server he wants to connect to.

		*/

		$dialog = new wxTextEntryDialog(
			$this,
			"Type in the port of the chat-server you want to connect to.",
			"Chat server port",
			$this->config_file_value_get( "port" )
		);

		if( $dialog->ShowModal() == wxID_OK )
		{
			$ret = $this->config_file_alter_keyvaluepair(
				"port",
				$dialog->GetValue()
			);

			if( $ret == FALSE )
			{
				$dialog_error = new wxMessageDialog(
					$this,
					"The port of the chat-server could not be changed",
					"Error",
					wxICON_ERROR
				);
			}
	 	}
	}


	function on_click_menu_extras_nickname()
	{
		/* Creates and shows a dialog where the user can change his username.

		*/
		$dialog = new wxTextEntryDialog(
			$this,
			"Type in your new nickname:",
			"Nickname",
			$this->config_file_value_get( "nickname" )
		);

		if( $dialog->ShowModal() == wxID_OK )
		{
			$ret = $this->config_file_alter_keyvaluepair(
				"nickname",
				$dialog->GetValue()
			);

			if( $ret == FALSE )
			{
				$dialog_error = new wxMessageDialog(
					$this,
					"The nickname could not be changed.",
					"Error",
					wxICON_ERROR
				);
			}
		}
	}


	function on_enter_pehachatpe_widget_message()
	{
		$this->message_to_send = $this->wxtextctrl_message->GetValue();
		$this->wxtextctrl_message->Clear();
	}


	function on_click_menu_file_connect()
	{
		/* Tries to connect to the chat-server.

		*/
		$chat_server_address = $this->config_file_value_get( "ip_address" );
		$chat_server_port = $this->config_file_value_get( "port" );
		$nickname = $this->config_file_value_get( "nickname" );
		
		$this->sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
		socket_set_nonblock( $this->sock );
		socket_connect( $this->sock, $chat_server_address, $chat_server_port );

		$this->wxtimer_reading->Start(
			1
		);
		$this->wxtimer_writing->Start(
			1
		);
	}


	function on_click_menu_file_disconnect()
	{
		/* Disconnects from the chat-server.

		*/
		socket_close( $this->sock );
		$this->wxtimer_reading->Stop();	
		$this->wxtimer_writing->Stop();	
	}


	function reading()
	{
		echo socket_read( $this->sock, 2048 );
	}


	function writing()
	{
		if( strlen( $this->message_to_send ) > 0 )
		{
			socket_write( $this->sock, $this->message_to_send, strlen( $this->message_to_send ) );
			$this->message_to_send = "";
		}
	}
}
?>
